# -*- coding: utf-8 -*-
# @Author: bao
# @Date:   2017-03-31 15:10:31
# @Last Modified by:   bao
# @Last Modified time: 2017-05-01 14:39:06
import sys
sys.path.append("..")

import re
import random
from CoreSim.MScheduler import *
from CoreSim.Flow import *
from CoreSim.Event import *
from CoreSim.Link import *
from CoreSim.Unit import *


def assignNewFlow(srcHost, dstHost, flows, flowSize, startTime, mcastFlowId, numHosts, numToRs, numCores):
    # unicast flow
    flow = Flow()
    flow.startId = srcHost
    flow.endId = dstHost
    flow.SetFlowSize(flowSize)
    flow.startTime = startTime
    flow.flowId = len(flows) + 1
    flow.mcastFlowId = mcastFlowId
    flows.append(flow)
    return flow

class MSchedulerUnicast(MScheduler):
    '''
    Multicast scheduler
    '''
    def __init__(self, topo_args, flow_args, conf_args):
        MScheduler.__init__(self, topo_args, flow_args, conf_args)
        self.type = 'unicast'

    def InitialMulticast(self, eventQueue):
        for mflowId in self.mcastFlows:
            mcastFlow = self.mcastFlows[mflowId]
            srcHost = mcastFlow.srcHost
            for dstHost in mcastFlow.dstHosts:
                # unicast flow
                flow = assignNewFlow(srcHost, dstHost, self.flows, mcastFlow.flowSize, mcastFlow.startTime, \
                mcastFlow.flowId, self.numHosts, self.numToRs, self.numCores)
                
                # eventqueue
                event = FlowArrivalEvent(flow.startTime, flow)
                eventQueue.push(event, event.time)
                
    def UpdateMulticast(self, mflowId, curFlow, curTime, eventqueue):
        mcastFlow = self.mcastFlows[mflowId]
        mcastFlow.dstHosts[curFlow.endId] = True
        if all(mcastFlow.dstHosts.values()):
            mcastFlow.finishTime = curTime
            for flow in self.flows:
                if flow.mcastFlowId == mflowId:
                    mcastFlow.energy += flow.energy
            print 'mcastFlow:%s transmission time %s energy %s'%(mflowId, mcastFlow.finishTime-mcastFlow.startTime, mcastFlow.energy)
